289577660c55a80baada1ca397c10af980464f9f,src/main/java/com/cronutils/model/time/ExecutionTime.java,ExecutionTime,previousClosestMatch,#DateTime#,233

Before Change


        if(year.isEmpty()){
            int previousYear = yearsValueGenerator.generatePreviousValue(date.getYear());
            if(highestDay>28){
                int highestDayOfMonth = new DateTime(previousYear, highestMonth, 1,0,0).dayOfMonth().getMaximumValue();
                if(highestDay>highestDayOfMonth){
                    nearestValue = days.getPreviousValue(highestDay, 1);
                    if(nearestValue.getShifts()>0){
                        newDate = new DateTime(previousYear, highestMonth, 1, 23, 59, 59, date.getZone())
                                .minusMonths(nearestValue.getShifts()).dayOfMonth().withMaximumValue();
                        return previousClosestMatch(newDate);
                    }else{
                        highestDay = nearestValue.getValue();
                    }
                }
            }
            return initDateTime(previousYear, highestMonth, highestDay, highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!months.getValues().contains(date.getMonthOfYear())){
            nearestValue = months.getPreviousValue(date.getMonthOfYear(), 0);
            int previousMonths = nearestValue.getValue();
            if(nearestValue.getShifts()>0){
                newDate =
                        new DateTime(date.getYear(), 12, 31, 23, 59, 59, date.getZone()).minusYears(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), previousMonths, highestDay, highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!days.getValues().contains(date.getDayOfMonth())){
            nearestValue = days.getPreviousValue(date.getDayOfMonth(), 0);
            if(nearestValue.getShifts()>0){
                newDate = new DateTime(date.getYear(), date.getMonthOfYear(), 1, 23, 59, 59, date.getZone())
                        .minusMonths(nearestValue.getShifts()).dayOfMonth().withMaximumValue();
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthOfYear(), nearestValue.getValue(), highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!hours.getValues().contains(date.getHourOfDay())){
            nearestValue = hours.getPreviousValue(date.getHourOfDay(), 0);
            if(nearestValue.getShifts()>0){
                newDate =
                        new DateTime(date.getYear(), date.getMonthOfYear(),
                                date.getDayOfMonth(), 23, 59, 59, date.getZone()).minusDays(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), nearestValue.getValue(), highestMinute, highestSecond, date.getZone());
        }
        if(!minutes.getValues().contains(date.getMinuteOfHour())){
            nearestValue = minutes.getPreviousValue(date.getMinuteOfHour(), 0);
            if(nearestValue.getShifts()>0){
                newDate =
                        new DateTime(date.getYear(), date.getMonthOfYear(),
                                date.getDayOfMonth(), date.getHourOfDay(), 59, 59, date.getZone()).minusHours(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(), date.getHourOfDay(), nearestValue.getValue(), highestSecond, date.getZone());
        }
        if(!seconds.getValues().contains(date.getSecondOfMinute())){
            nearestValue = seconds.getPreviousValue(date.getSecondOfMinute(), 0);
            int previousSeconds = nearestValue.getValue();
            if(nearestValue.getShifts()>0){
                newDate =
                        new DateTime(date.getYear(), date.getMonthOfYear(),
                                date.getDayOfMonth(), date.getHourOfDay(),
                                date.getMinuteOfHour(), 59, date.getZone()).minusMinutes(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }

After Change


     * @return ZonedDateTime instance, never null. Value obeys logic specified above.
     * @throws NoSuchValueException
     */
    ZonedDateTime previousClosestMatch(ZonedDateTime date) throws NoSuchValueException {
        List<Integer> year = yearsValueGenerator.generateCandidates(date.getYear(), date.getYear());
        TimeNode days = generateDays(cronDefinition, date);
        int highestMonth = months.getValues().get(months.getValues().size()-1);
        int highestDay = days.getValues().get(days.getValues().size()-1);
        int highestHour = hours.getValues().get(hours.getValues().size()-1);
        int highestMinute = minutes.getValues().get(minutes.getValues().size()-1);
        int highestSecond = seconds.getValues().get(seconds.getValues().size()-1);

        NearestValue nearestValue;
        ZonedDateTime newDate;
        if(year.isEmpty()){
            int previousYear = yearsValueGenerator.generatePreviousValue(date.getYear());
            if(highestDay>28){
                int highestDayOfMonth = LocalDate.of(previousYear, highestMonth, 1).lengthOfMonth();
                if(highestDay>highestDayOfMonth){
                    nearestValue = days.getPreviousValue(highestDay, 1);
                    if(nearestValue.getShifts()>0){
                        newDate = ZonedDateTime.of(LocalDateTime.of(previousYear, highestMonth, 1, 23, 59, 59), ZoneId.systemDefault())
                                .minusMonths(nearestValue.getShifts()).with(lastDayOfMonth());
                        return previousClosestMatch(newDate);
                    }else{
                        highestDay = nearestValue.getValue();
                    }
                }
            }
            return initDateTime(previousYear, highestMonth, highestDay, highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!months.getValues().contains(date.getMonthValue())){
            nearestValue = months.getPreviousValue(date.getMonthValue(), 0);
            int previousMonths = nearestValue.getValue();
            if(nearestValue.getShifts()>0){
                newDate =
                        ZonedDateTime.of(LocalDateTime.of(date.getYear(), 12, 31, 23, 59, 59), date.getZone()).minusYears(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), previousMonths, highestDay, highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!days.getValues().contains(date.getDayOfMonth())){
            nearestValue = days.getPreviousValue(date.getDayOfMonth(), 0);
            if(nearestValue.getShifts()>0){
                newDate = ZonedDateTime.of(LocalDateTime.of(date.getYear(), date.getMonthValue(), 1, 23, 59, 59), date.getZone())
                        .minusMonths(nearestValue.getShifts()).with(lastDayOfMonth());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthValue(), nearestValue.getValue(), highestHour, highestMinute, highestSecond, date.getZone());
        }
        if(!hours.getValues().contains(date.getHour())){
            nearestValue = hours.getPreviousValue(date.getHour(), 0);
            if(nearestValue.getShifts()>0){
                newDate =
                        ZonedDateTime.of(LocalDateTime.of(date.getYear(), date.getMonthValue(),
                                date.getDayOfMonth(), 23, 59, 59), date.getZone()).minusDays(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthValue(), date.getDayOfMonth(), nearestValue.getValue(), highestMinute, highestSecond, date.getZone());
        }
        if(!minutes.getValues().contains(date.getMinute())){
            nearestValue = minutes.getPreviousValue(date.getMinute(), 0);
            if(nearestValue.getShifts()>0){
                newDate =
                        ZonedDateTime.of(LocalDateTime.of(date.getYear(), date.getMonthValue(),
                                date.getDayOfMonth(), date.getHour(), 59, 59), date.getZone()).minusHours(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }
            return initDateTime(date.getYear(), date.getMonthValue(), date.getDayOfMonth(), date.getHour(), nearestValue.getValue(), highestSecond, date.getZone());
        }
        if(!seconds.getValues().contains(date.getSecond())){
            nearestValue = seconds.getPreviousValue(date.getSecond(), 0);
            int previousSeconds = nearestValue.getValue();
            if(nearestValue.getShifts()>0){
                newDate =
                        ZonedDateTime.of(LocalDateTime.of(date.getYear(), date.getMonthValue(),
                                date.getDayOfMonth(), date.getHour(),
                                date.getMinute(), 59), date.getZone()).minusMinutes(nearestValue.getShifts());
                return previousClosestMatch(newDate);
            }